package com.iims.flowable.controller;

import cn.hutool.core.codec.Base64;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.google.common.collect.ImmutableMap;
import com.iims.common.annotation.Log;
import com.iims.common.core.domain.AjaxResult;
import com.iims.common.core.page.TableDataInfo;
import com.iims.common.enums.BusinessType;
import com.iims.flowable.common.constant.FlowableConstant;
import com.iims.flowable.common.enums.FlowActiveEnum;
import com.iims.flowable.factory.BaseFlowableController;
import com.iims.flowable.flow.vo.request.FlowActiveSuspendRequest;
import com.iims.flowable.flow.vo.request.FlowDeleteRequest;
import com.iims.flowable.flow.vo.request.FlowProcDefQueryVo;
import com.iims.flowable.flow.vo.request.FlowSaveXmlVo;
import com.iims.flowable.flow.vo.resp.FlowProcDefDto;
import com.iims.flowable.flow.vo.wrapper.WrapperFlowProcDefList;
import com.iims.flowable.service.IFlowDefinitionService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.engine.impl.ProcessDefinitionQueryProperty;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 工作流程定义
 * </p>
 *
 * @author fanpei
 * @date 2021-04-03
 */
@Slf4j
@Api(tags = "流程定义")
@ApiSort(1)
@RestController
@RequestMapping("/flowable/definition")
public class FlowDefinitionController extends BaseFlowableController {

    @Autowired
    private IFlowDefinitionService flowDefinitionService;


    private static final Map<String, QueryProperty> ALLOWED_SORT_PROPERTIES = new HashMap<>();

    static {
        ALLOWED_SORT_PROPERTIES.put(FlowableConstant.ID, ProcessDefinitionQueryProperty.PROCESS_DEFINITION_ID);
        ALLOWED_SORT_PROPERTIES.put(FlowableConstant.KEY, ProcessDefinitionQueryProperty.PROCESS_DEFINITION_KEY);
        ALLOWED_SORT_PROPERTIES.put(FlowableConstant.CATEGORY, ProcessDefinitionQueryProperty.PROCESS_DEFINITION_CATEGORY);
        ALLOWED_SORT_PROPERTIES.put(FlowableConstant.NAME, ProcessDefinitionQueryProperty.PROCESS_DEFINITION_NAME);
        ALLOWED_SORT_PROPERTIES.put(FlowableConstant.VERSION, ProcessDefinitionQueryProperty.PROCESS_DEFINITION_VERSION);
        ALLOWED_SORT_PROPERTIES.put(FlowableConstant.TENANT_ID, ProcessDefinitionQueryProperty.PROCESS_DEFINITION_TENANT_ID);
    }


    @ApiOperation(value = "分页获取流程列表", response = FlowProcDefDto.class)
    @ApiOperationSupport(order = 1, ignoreParameters = {"orderByColumn", "isAsc"})
    @GetMapping(value = "/list")
    public TableDataInfo list(FlowProcDefQueryVo flowProcDefVo) throws Exception {
        //flowProcDefVo.setPageDomain(getPageDomain());
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        return this.pageList(flowProcDefVo, query, WrapperFlowProcDefList.class, ALLOWED_SORT_PROPERTIES);
    }

    @ApiOperation(value = "获取所有流程分类")
    @ApiOperationSupport(order = 2)
    @GetMapping(value = "/category/list")
    public AjaxResult categoryList() throws Exception {
        return AjaxResult.success(flowDefinitionService.categoryList());
    }

    @ApiOperation(value = "获取流程xml文件")
    @ApiOperationSupport(order = 3)
    @GetMapping("/readXml/{processDefinitionId}")
    public AjaxResult readXml(@ApiParam(value = "流程定义id") @PathVariable String processDefinitionId) {
        try {
            return flowDefinitionService.readXml(processDefinitionId);
        } catch (Exception e) {
            return AjaxResult.error("加载xml文件异常");
        }

    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "获取流程定义图")
    @GetMapping("/readImage/{processDefinitionId}")
    public AjaxResult readImage(@ApiParam(value = "流程定义id") @PathVariable(value = "processDefinitionId") String processDefinitionId, HttpServletResponse response) {
        //sendImageStream(response, flowDefinitionService.readImage(processDefinitionId));
        return AjaxResult.success("流程图获取成功",Base64.encode(flowDefinitionService.readImage(processDefinitionId)));
    }


    @ApiOperation(value = "导入流程", notes = "上传bpmn20的xml文件")
    @ApiOperationSupport(order = 5)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "流程名称", name = "name", paramType = "query", required = true),
            @ApiImplicitParam(value = "流程分类", name = "category", paramType = "query", required = true),
            @ApiImplicitParam(value = "流程文件:bpmn20的xml文件", name = "file", paramType = "formData", dataType = "file", required = true)
    })
    @Log(title = "导入流程", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('flowable:flow_define:import')")
    @PostMapping("/import")
    public AjaxResult importFile(@RequestParam String name,
                                 @RequestParam String category,
                                 @RequestBody MultipartFile file,
                                 HttpServletRequest request) {
        return flowDefinitionService.importFile(name, category, file.getOriginalFilename(), file, request);
    }


    @ApiOperation(value = "新增流程")
    @ApiOperationSupport(order = 6)
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PreAuthorize("@ss.hasPermi('system:flow_define:edit')")
    @PostMapping("/save")
    public AjaxResult save(@Validated @RequestBody FlowSaveXmlVo vo, HttpServletRequest request) {
        ByteArrayResource in = new ByteArrayResource(vo.getXml().getBytes(StandardCharsets.UTF_8));
        String filename = vo.getName() + "bpmn20.xml";
        return flowDefinitionService.importFile(vo.getName(), vo.getCategory(), filename, in, request);
    }

    @ApiOperation(value = "激活挂起流程")
    @ApiOperationSupport(order = 7, ignoreParameters = "processInstanceId")
    @Log(title = "流程定义", businessType = BusinessType.UPDATE)
    @PreAuthorize("@ss.hasPermi('system:flow_define:suspendOrActivate')")
    @PutMapping(value = "/updateState")
    public AjaxResult updateState(@RequestBody FlowActiveSuspendRequest activeSuspendQueryVo) {
        if (FlowActiveEnum.ACTIVE.getValue() == activeSuspendQueryVo.getStatus()) {
            flowDefinitionService.activate(activeSuspendQueryVo);
        } else {
            flowDefinitionService.suspend(activeSuspendQueryVo);
        }
        return AjaxResult.success();
    }

    @ApiOperation(value = "删除流程")
    @ApiOperationSupport(order = 8, ignoreParameters = {"processInstanceId", "deleteReason"})
    @Log(title = "流程定义", businessType = BusinessType.DELETE)
    @PreAuthorize("@ss.hasPermi('system:flow_define:remove')")
    @DeleteMapping(value = "/delete")
    public AjaxResult delete(@RequestBody FlowDeleteRequest flowDeleteQueryVo) {
        flowDefinitionService.delete(flowDeleteQueryVo.getProcessDefinitionId(), flowDeleteQueryVo.getCascade());
        return AjaxResult.success();
    }

    @ApiOperation(value = "查询流程起始表单")
    @ApiOperationSupport(order = 9)
    @GetMapping(value = "/renderedStartForm")
    public AjaxResult renderedStartForm(@RequestParam String processDefinitionId) {
        permissionService.validateReadPermissionOnProcessDefinition(getLoginUserCode(), processDefinitionId);
        Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId);
        boolean showBusinessKey = this.isShowBusinessKey(processDefinitionId);
        return AjaxResult.success(ImmutableMap.of("renderedStartForm", renderedStartForm != null ? renderedStartForm : "",
                "showBusinessKey", showBusinessKey));
    }


/*
删除接口复用角色和用户接口 fanpei 2021-06-08

 @ApiOperation(value = "指定流程办理人员列表")
    @GetMapping("/userList")
    public AjaxResult userList(SysUser user) {
        List<SysUser> list = userService.selectUserList(user);
        return AjaxResult.success(list);
    }

    @ApiOperation(value = "指定流程办理组列表")
    @GetMapping("/roleList")
    public AjaxResult roleList(SysRole role) {
        List<SysRole> list = sysRoleService.selectRoleList(role);
        return AjaxResult.success(list);
    }*/

}